package com.yj.handler;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.yj.anno.RpcService;
import com.yj.common.RpcRequest;
import com.yj.common.RpcResponse;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class RpcServerHandler extends SimpleChannelInboundHandler<String> implements  ApplicationListener<ContextRefreshedEvent> {

    private static final Map<String, Object> SERVER_INSTANCE_MAP = new HashMap<>();

    private ApplicationContext applicationContext;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        RpcRequest rpcRequest = JSON.parseObject(msg, RpcRequest.class);

        String requestId = rpcRequest.getRequestId();
        RpcResponse rpcResponse = null;

        try {
            // 处理请求
            Object result = handle(rpcRequest);

            rpcResponse = new RpcResponse();
            rpcResponse.setRequestId(requestId);
            rpcResponse.setResult(result);
        } catch (Exception e) {
            rpcResponse.setError(e.getMessage());
            log.error("处理请求失败:{}",e.getMessage());
        }
        // 响应请求
        ctx.writeAndFlush(JSONUtil.toJsonStr(rpcResponse));
    }

    private Object handle(RpcRequest rpcRequest) {
        String className = rpcRequest.getClassName();
        Object object = SERVER_INSTANCE_MAP.get(className);
        if (object == null) {
            log.error("服务[{}]未注册到服务注册中心", className);
            return String.format("服务[%s]未注册到服务注册中心", className);
        }

        String methodName = rpcRequest.getMethodName();
        Class<?>[] parameterTypes = rpcRequest.getParameterTypes();
        Object[] parameters = rpcRequest.getParameters();
        try {
            // 通过参数类型获取方法对象，因为可能存在重载方法
            Method method = object.getClass().getMethod(methodName, parameterTypes);
            return method.invoke(object, parameters);
        } catch (Exception e) {
            log.error("处理请求失败:{}", e.getMessage());
            return null;
        }
    }


    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        this.applicationContext = event.getApplicationContext();
        Map<String, Object> map = applicationContext.getBeansWithAnnotation(RpcService.class);

        if (map.isEmpty()) {
            log.warn("未找到任何RpcService注解的Bean");
            return;
        }
        map.entrySet().stream().forEach(entry -> {
            String beanName = entry.getKey();
            Object bean = entry.getValue();

            Class<?>[] interfaces = bean.getClass().getInterfaces();
            if (interfaces.length == 0){
                log.error("RpcService注解的Bean[{}]没有实现接口",beanName);
                return;
            }
            // 默认取第一个接口
            Class<?> anInterface = interfaces[0];
            String serviceName = anInterface.getName();

            SERVER_INSTANCE_MAP.put(serviceName, bean);
            log.info("注册服务[{}]到服务注册中心",serviceName);
        });
    }

}
